#include "NetPacket.h"
#include "NetConstants.h"
#include <stdlib.h>
#include "NetUtils.h"
#include "NetDebug.h"

namespace LiteNetLib
{

    static uint32_t HeaderSizes[(uint8_t)PacketProperty::Empty + 1] =
    {
        1,      // PacketProperty::Unreliable
        4,      // PacketProperty::Channeled
        4,      // PacketProperty::Ack
        3,      // PacketProperty::Ping
        11,     // PacketProperty::Pong
        14,     // PacketProperty::ConnectRequest
        11,     // PacketProperty::ConnectAccept
        9,      // PacketProperty::Disconnect
        1,      // PacketProperty::UnconnectedMessage
        1,      // PacketProperty::MtuCheck
        1,      // PacketProperty::MtuOk
        1,      // PacketProperty::Broadcast
        1,      // PacketProperty::Merged
        1,      // PacketProperty::ShutdownOk
        1,      // PacketProperty::PeerNotFound
        1,      // PacketProperty::InvalidProtocol
        1,      // PacketProperty::NatMessage
        1       // PacketProperty::Empty
    };

    /** ConnectRequest
     * 
     *                      connectionID                  addressData
     *                           |                            |
     *  | 1x byte | 4 x byte | 8 x byte | 1 x byte | addressSize x byte | ... |
     *      |         |                      |                             |
     *     0x06     unknow               addressSize                    user data
     *      |                                |
     *      +---------- Header Size ---------+
     *                      |
     *                    14 x byte
     * 
     * 
     * 
     * 
     * 
    */








    uint32_t NetPacket::GetHeaderSize(PacketProperty type)
    {
        return HeaderSizes[(uint8_t)type];
    }

    std::atomic<int32_t> nowPackCount;

    NetPacket::NetPacket(uint32_t packetSize)
    {
        m_packetSize = packetSize;
        uint32_t rawDataSize = packetSize;
        m_rawData = (char *)malloc(rawDataSize);
        m_rawData[0] = 0;
        m_rawDataSize = rawDataSize;
        nowPackCount++;
    }

    NetPacket::NetPacket(PacketProperty property, uint32_t packetSize) : NetPacket( (HeaderSizes[(uint8_t)property] + packetSize) )
    {
        setProperty(property);
    }

    NetPacket::~NetPacket()
    {
        if(m_rawData != nullptr)
        {
            free(m_rawData);
        }
        nowPackCount--;
    }

    void NetPacket::expansionRawDataSize(uint32_t newRawDataSize)
    {
        if(newRawDataSize > m_rawDataSize)
        {
            free(m_rawData);
            m_rawData = (char *)malloc(newRawDataSize);
            m_rawDataSize = newRawDataSize;
        }
    }

    void NetPacket::resetPacketSize(uint32_t newPacketSize)
    {
        expansionRawDataSize(newPacketSize);
        m_rawData[0] = 0;
        m_packetSize = newPacketSize;
    }

    // ======================== 查询和设置包头 ========================
    PacketProperty NetPacket::getProperty()
    {
        return (PacketProperty)(m_rawData[0] & 0x1F);
    }
    void NetPacket::setProperty(PacketProperty value)
    {
        m_rawData[0] = (uint8_t)((m_rawData[0] & 0xE0) | (uint8_t)value);
    }

    // ======================== 获取和设置连接编号 =====================
    uint8_t NetPacket::getConnectionNumber()
    {
        return (uint8_t)((m_rawData[0] & 0x60) >> 5);
    }
    void NetPacket::setConnectionNumber(uint8_t value)
    {
        m_rawData[0] = (uint8_t)((m_rawData[0] & 0x9F) | (value << 5));
    }

    // ======================== 获取和设置序列 ========================
    uint16_t NetPacket::getSequence()
    {
        return NetUtils::ByteToUInt16(&m_rawData[1]);
    }
    void NetPacket::setSequence(uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[1], value);
    }

    // ======================== 是否碎片化的 ==========================
    bool NetPacket::isFragmented()
    {
        return (m_rawData[0] & 0x80) != 0;
    }
    void NetPacket::markFragmented()
    {
        m_rawData[0] |= 0x80;
    }

    // ======================== 获取和设置通道ID ======================
    uint8_t NetPacket::getChannelId()
    {
        return m_rawData[3];
    }
    void NetPacket::setChannelId(uint8_t value)
    {
        m_rawData[3] = value;
    }

    // ======================== 获取和设置片段ID ======================
    uint16_t NetPacket::getFragmentId()
    {
        return NetUtils::ByteToUInt16(&m_rawData[4]);
    }
    void NetPacket::setFragmentId(uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[4], value);
    }

    // ======================== 获取和设置片段部分 =====================
    uint16_t NetPacket::getFragmentPart()
    {
        return NetUtils::ByteToUInt16(&m_rawData[6]);
    }
    void NetPacket::setFragmentPart(uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[6], value);
    }

    // ======================== 获取片段总数 ==========================
    uint16_t NetPacket::getFragmentsTotal()
    {
        return NetUtils::ByteToUInt16(&m_rawData[8]);
    }
    void NetPacket::setFragmentsTotal(uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[8], value);
    }

    // ================================ 校验 ================================
    bool NetPacket::verify()
    {
        uint8_t property = (uint8_t)(m_rawData[0] & 0x1F);
        if (property > (uint8_t)PacketProperty::Empty)
        {
            return false;
        }
        uint32_t headerSize = HeaderSizes[property];
        bool fragmented = (m_rawData[0] & 0x80) != 0;
        return m_packetSize >= headerSize && (!fragmented || m_packetSize >= headerSize + NetConstants::FragmentHeaderSize);
    }





    // ======================== 查询和设置包头 ========================
    PacketProperty NetPacket::GetProperty(const char *m_rawData)
    {
        return (PacketProperty)(m_rawData[0] & 0x1F);
    }
    void NetPacket::SetProperty(char *m_rawData, PacketProperty value)
    {
        m_rawData[0] = (uint8_t)((m_rawData[0] & 0xE0) | (uint8_t)value);
    }

    // ======================== 获取和设置连接编号 =====================
    uint8_t NetPacket::GetConnectionNumber(const char* m_rawData)
    {
        return (uint8_t)((m_rawData[0] & 0x60) >> 5);
    }
    void NetPacket::SetConnectionNumber(char *m_rawData, uint8_t value)
    {
        m_rawData[0] = (uint8_t)((m_rawData[0] & 0x9F) | (value << 5));
    }

    // ======================== 获取和设置序列 ========================
    uint16_t NetPacket::GetSequence(const char* m_rawData)
    {
        return NetUtils::ByteToUInt16(&m_rawData[1]);
    }
    void NetPacket::SetSequence(char* m_rawData, uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[1], value);
    }

    // ======================== 是否碎片化的 ==========================
    bool NetPacket::IsFragmented(const char *m_rawData)
    {
        return (m_rawData[0] & 0x80) != 0;
    }
    void NetPacket::MarkFragmented(char * m_rawData)
    {
        m_rawData[0] |= 0x80;
    }

    // ======================== 获取和设置通道ID ======================
    uint8_t NetPacket::GetChannelId(const char *m_rawData)
    {
        return m_rawData[3];
    }
    void NetPacket::SetChannelId(char *m_rawData, uint8_t value)
    {
        m_rawData[3] = value;
    }

    // ======================== 获取和设置片段ID ======================
    uint16_t NetPacket::GetFragmentId(const char* m_rawData)
    {
        return NetUtils::ByteToUInt16(&m_rawData[4]);
    }
    void NetPacket::SetFragmentId(char *m_rawData, uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[4], value);
    }

    // ======================== 获取和设置片段部分 =====================
    uint16_t NetPacket::GetFragmentPart(const char* m_rawData)
    {
        return NetUtils::ByteToUInt16(&m_rawData[6]);
    }
    void NetPacket::SetFragmentPart(char *m_rawData, uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[6], value);
    }

    // ======================== 获取片段总数 ==========================
    uint16_t NetPacket::GetFragmentsTotal(const char* m_rawData)
    {
        return NetUtils::ByteToUInt16(&m_rawData[8]);
    }
    void NetPacket::SetFragmentsTotal(char *m_rawData, uint16_t value)
    {
        NetUtils::UInt16ToByte(&m_rawData[8], value);
    }

    // ================================ 校验 ================================
    bool NetPacket::Verify(const char *theData, uint32_t dataSize)
    {
        uint8_t property = (uint8_t)(theData[0] & 0x1F);
        if (property > (uint8_t)PacketProperty::Empty)
        {
            return false;
        }
        int32_t headerSize = HeaderSizes[property];
        bool fragmented = (theData[0] & 0x80) != 0;

        // NetDebug::Info("dataSize: {}, headerSize: {}, fragmented: {}, FragmentHeaderSize: {}", dataSize, headerSize, fragmented, NetConstants::FragmentHeaderSize);
        return dataSize >= headerSize && (!fragmented || dataSize >= headerSize + NetConstants::FragmentHeaderSize);
    }

}

